#pragma once
// 使用数据库
#include <iostream>
#include <string>
#include <vector>
#include <unordered_map>
#include <cassert>
#include <mysql/mysql.h>

#include "../comm/Log.hpp"
#include "../comm/util.hpp"

namespace ns_model
{
    using namespace ns_util;
    struct Question
    {
        std::string _qid; // 题目编号
        std::string _title; // 题目
        std::string _difficulty; // 难度
        int _cpu_limit; // 时间限制
        int _mem_limit; // 空间限制
        std::string _desc; // 题目的描述
        std::string _header; // 题目中编辑器里的内容
        std::string _tail; // 测试用例，与_header拼接形成完整代码
    };

    const std::string oj_questions = "oj_questions";
    const std::string host = "127.0.0.1";
    const std::string user = "lw";
    const std::string passwd = "Liwei200408#";
    const std::string db = "oj";
    const uint16_t port = 3306;
    
    class Model
    {
    public:
        Model()
        {
            
        }

        bool SqlQuery(const std::string& sql, std::vector<Question>* out)
        {
            MYSQL mysql;
            mysql_init(&mysql);
            if(nullptr ==mysql_real_connect(&mysql, host.c_str(), user.c_str(), passwd.c_str(), db.c_str(), port, nullptr, 0))
            {
                LOG(FATAL, "连接数据库失败\n");
                return false;
            }
            LOG(INFO, "连接数据库成功\n");
            if(0 != mysql_query(&mysql, sql.c_str()))
            {
                LOG(ERROR, "执行 sql 语句: %s ...失败\n", sql.c_str());
                return false;
            }
            MYSQL_RES* res = mysql_store_result(&mysql);

            int rows = mysql_num_rows(res);
            int cols = mysql_num_fields(res);
            if(cols != 8)
            {
                LOG(ERROR, "执行 sql 语句: %s ...获取的列数有问题\n", sql.c_str());
                return false;
            }

            for(int i = 0; i < rows; ++i)
            {
                MYSQL_ROW line = mysql_fetch_row(res);
                
                Question q;
                q._qid = line[0];
                q._title = line[1];
                q._difficulty = line[2];
                q._desc = line[3];
                q._header = line[4];
                q._tail = line[5];
                q._cpu_limit = std::stoi(line[6]);
                q._mem_limit = std::stoi(line[7]);

                out->push_back(q);
            }

            mysql_free_result(res);
            mysql_close(&mysql);
            return true;
        }

        bool GetAllQuestion(std::vector<Question>* out)
        {
            std::string sql = "select * from ";
            sql += oj_questions;
            return SqlQuery(sql, out);
        }

        bool GetOneQuestion(std::string number, Question* q)
        {
            std::string sql = "select * from ";
            sql += oj_questions;
            sql += " where qid=";
            sql += number;

            std::vector<Question> res;
            if(SqlQuery(sql, &res))
            {
                if(res.size() == 1)
                {
                    *q = res[0];
                    return true;
                }
            }
            return false;
        }

        ~Model()
        {}
    private:
        std::unordered_map<std::string, Question> _questions; // 题目编号与题目的映射
    };
}